package com.maiji.cloud.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.google.common.collect.Maps;
import com.maiji.cloud.config.MyRedisConfig;
import com.maiji.cloud.entities.login.AppUser;
import com.maiji.cloud.entities.login.UploadRecord;
import com.maiji.cloud.entities.shopingmall.*;
import com.maiji.cloud.mapper.GoodsCommentMapper;
import com.maiji.cloud.microservice.UploadRecordService;
import com.maiji.cloud.microservice.UserInfoService;
import com.maiji.cloud.request.ReqMetaData;
import com.maiji.cloud.request.shopingmall.GoodsCommentFindAllReqData;
import com.maiji.cloud.response.*;
import com.maiji.cloud.response.login.UploadImageResData;
import com.maiji.cloud.service.*;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.maiji.cloud.utils.BaseService;
import com.maiji.cloud.utils.RedisUtil;
import com.maiji.cloud.utils.UUID_MD5;
import org.eclipse.jetty.util.StringUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional
public class GoodsCommentServiceImpl extends ServiceImpl<GoodsCommentMapper, GoodsComment> implements GoodsCommentService {

    public static final String REDISNAMESPACE = "goodsComment";
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private GoodsCommentMapper goodsCommentMapper;
    @Autowired
    private GoodsCommentCommentService goodsCommentCommentService;
    @Autowired
    private GoodsCommentThumbsUpService goodsCommentThumbsUpService;
    @Autowired
    private UploadRecordService uploadRecordService;
    @Autowired
    private LabelMiddleGoodsCommentService labelMiddleGoodsCommentService;
    @Autowired
    private ShopingOrderService shopingOrderService;
    @Autowired
    private GoodsService goodsService;

    @Override
    public BaseMetaResDto<List<GoodsComment>> findAllGoodsComment(GoodsCommentFindAllReqData data, ReqMetaData metaData, String token) {
        // 获取商品评论[]
        Page<GoodsComment> page = new Page<>(metaData.getPage(), metaData.getSize());
        if (StringUtil.isNotBlank(token)) {
            AppUser appUser = RedisUtil.getAppUserByRedis(redisTemplate, MyRedisConfig.REDISDATABASENO, token, userInfoService);
            data.setUserId(appUser.getUuId());
        }
        List<GoodsComment> goodsComments = goodsCommentMapper.findAllGoodsComment(data, page);
        if (goodsComments != null && goodsComments.size() > 0) {
            List<String> gcIds = goodsComments.stream().map(GoodsComment::getUuId).collect(Collectors.toList());
            // 获取商品评论图片[]
            HashMap<String, Object> map = Maps.newHashMap();
            map.put("belongIds", gcIds);
            List<UploadImageResData> gcImgs = uploadRecordService.findAllByBelongIds(map)
                    .stream().map(uploadRecord -> {
                        UploadImageResData uploadImageResData = new UploadImageResData();
                        BeanUtils.copyProperties(uploadRecord, uploadImageResData);
                        return uploadImageResData.setSmallUrl(uploadRecord.getUrl() + "?x-oss-process=image/resize,l_500");
                    }).collect(Collectors.toList());
            if (gcImgs.size() > 0) goodsComments = BaseService.dealWithOneToMany(goodsComments, "getUuId", GoodsComment.class,
                    "setCommentImages", gcImgs, "getBelongId", UploadImageResData.class);
            // 获取商品评论回复[]
            EntityWrapper<GoodsCommentComment> entityWrapper = new EntityWrapper<>();
            entityWrapper.in("comment_id", gcIds);
            entityWrapper.orderBy("comment_date", true);
            List<GoodsCommentComment> gccs = goodsCommentCommentService.selectList(entityWrapper);
            if (gccs.size() > 0) goodsComments = BaseService.dealWithOneToMany(goodsComments, "getUuId", GoodsComment.class,
                    "setCommentComments", gccs, "getCommentId", GoodsCommentComment.class);
            goodsComments = goodsComments.stream().map(gc -> {
                if (StringUtil.isNotBlank(data.getUserId()) && gc.getUserId().equals(data.getUserId())) gc.setIsMine(true);
                return gc;
            }).collect(Collectors.toList());
        }
        ResMetaData resMetaData = new ResMetaData(page.getCurrent(), page.getSize(), page.getTotal());
        return new BaseMetaResDto<List<GoodsComment>>(Status.SUCCESS).setData(goodsComments).setResMetaData(resMetaData);
    }

    @Override
    public BaseMetaResDto<GoodsComment> findGoodsCommentById(String goodsCommentId, String token) {
        String redisKey = RedisUtil.getRedisKey(REDISNAMESPACE, goodsCommentId);
        GoodsComment goodsComment = (GoodsComment) redisTemplate.opsForValue().get(redisKey);
        if (goodsComment == null)
            goodsComment = goodsCommentMapper.findGoodsCommentById(goodsCommentId);
        if (goodsComment == null) return new BaseMetaResDto(Status.ERROR);
        if (StringUtil.isNotBlank(token)) {
            AppUser appUser = RedisUtil.getAppUserByRedis(redisTemplate, MyRedisConfig.REDISDATABASENO, token, userInfoService);
            goodsComment.setIsMine(goodsComment.getUserId().equals(appUser.getUuId()));
        }
        RedisUtil.setObject(redisTemplate, redisKey, goodsComment);
        return new BaseMetaResDto<GoodsComment>(Status.SUCCESS).setData(goodsComment);
    }

    @Override
    @Transactional(isolation = Isolation.READ_UNCOMMITTED)
    public BaseResDto thumbsUpGoodsCommentById(String goodsCommentId, String token) {
        AppUser appUser = RedisUtil.getAppUserByRedis(redisTemplate, MyRedisConfig.REDISDATABASENO, token, userInfoService);
        String userId = appUser.getUuId();
        GoodsComment goodsComment = selectById(goodsCommentId);
        GoodsCommentThumbsUp goodsCommentThumbsUp = goodsCommentThumbsUpService.selectOneByRedis(goodsCommentId, userId);
        if (goodsCommentThumbsUp == null) {
            goodsCommentThumbsUp = new GoodsCommentThumbsUp();
            goodsCommentThumbsUp.setUuId(UUID_MD5.getUUID())
                    .setGoodsCommentId(goodsCommentId)
                    .setUserId(userId)
                    .setThumbsUpDate(new Date())
                    .setIsCancel(0);
            if (goodsCommentThumbsUpService.insert(goodsCommentThumbsUp))
                goodsComment.setThumbsUpNo(goodsComment.getThumbsUpNo() + 1);
        } else {
            Integer isCancel = goodsCommentThumbsUp.getIsCancel();
            goodsCommentThumbsUp.setIsCancel(isCancel==1? 0: 1);
            if (goodsCommentThumbsUpService.updateById(goodsCommentThumbsUp))
                goodsComment.setThumbsUpNo(goodsComment.getThumbsUpNo() + (isCancel==1? 1: -1));
        }
        if (updateById(goodsComment)) {
            String redisKey = RedisUtil.getRedisKey(goodsCommentThumbsUpService.REDISNAMESPACE, goodsCommentId, userId);
            RedisUtil.setObject(redisTemplate, redisKey, goodsCommentThumbsUp);
            redisTemplate.delete(REDISNAMESPACE + goodsCommentId);
            return new BaseResDto(Status.SUCCESS);
        } else thumbsUpGoodsCommentById(goodsCommentId, token);
        return new BaseResDto(Status.ERROR);
    }

    @Override
    public BaseResDto publishGoodsComment(String orderId, String goodsId, String content, Integer star,
                                          List<String> commentLabelIds, List<String> commentImageIds, String token) {
        AppUser appUser = RedisUtil.getAppUserByRedis(redisTemplate, MyRedisConfig.REDISDATABASENO, token, userInfoService);
        ShopingOrder shopingOrder = shopingOrderService.selectById(orderId);
        String goodsCommentId = UUID_MD5.getUUID();
        GoodsComment goodsComment = new GoodsComment()
                .setUuId(goodsCommentId)
                .setOrderId(orderId)
                .setOrderNo(shopingOrder.getOrderNo())
                .setUserId(appUser.getUuId())
                .setGoodsId(goodsId)
                .setContent(content)
                .setStar(star)
                .setCommentDate(new Date());
        if (! insert(goodsComment)) return new BaseResDto(Status.ERROR).setMessage("插入商品评论失败");
        Goods goods = goodsService.selectById(goodsId);
        goods.setCommentCount(goods.getCommentCount() + 1);
        if (! goodsService.updateById(goods)) return new BaseResDto(Status.ERROR).setMessage("修改商品评论数量失败");
        if (commentLabelIds != null && commentLabelIds.size() != 0) {
            List<LabelMiddleGoodsComment> labelMiddleGoodsComments = commentLabelIds.stream().map(labelId -> new LabelMiddleGoodsComment()
                    .setUuId(UUID_MD5.getUUID()).setGoodsCommentId(goodsCommentId).setLabelId(labelId)).collect(Collectors.toList());
            if (! labelMiddleGoodsCommentService.insertBatch(labelMiddleGoodsComments)) return new BaseResDto(Status.ERROR);
        }
        if (commentImageIds != null && commentImageIds.size() != 0) {
            List<UploadRecord> uploadRecords = commentImageIds.stream().map(imgId -> new UploadRecord()
                    .setUuId(imgId).setBelongId(goodsCommentId)).collect(Collectors.toList());
            if (! uploadRecordService.updateBatchUploadRecord(uploadRecords)) return new BaseResDto(Status.ERROR);
        }
        if (! shopingOrderService.updateById(shopingOrder.setStatus(5)))
            return new BaseResDto(Status.ERROR).setMessage("修改订单状态为已评价失败");
        return new BaseResDto(Status.SUCCESS);
    }

    @Override
    public BaseResDto delGoodsComment(String gcId) {
        GoodsComment goodsComment = selectById(gcId);
        Goods goods = goodsService.selectById(goodsComment.getGoodsId());
        Integer shield = goodsComment.getShield();
        if (shield == 0) goods.setCommentCount(goods.getCommentCount() - 1);
        if (shield == 1) goods.setCommentVolume(goods.getCommentVolume() - 1);
        if (! goodsService.updateById(goods)) return new BaseResDto(Status.ERROR).setMessage("修改商品评论数量失败");
        if (deleteById(gcId)) return new BaseResDto(Status.SUCCESS);
        return new BaseResDto(Status.ERROR);
    }

    @Override
    public BaseResDto shieldGoodsComment(String goodsId, String gcId, Integer shield) {
        GoodsComment goodsComment = selectById(gcId);
        if (! updateById(goodsComment.setShield(shield))) return new BaseResDto(Status.SUCCESS);
        Goods goods = goodsService.selectById(goodsId);
        EntityWrapper<GoodsComment> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("goods_id", goodsId);
        entityWrapper.eq("shield", 0);
        entityWrapper.eq("is_del", 0);
        goods.setCommentCount(selectCount(entityWrapper));
        if (shield == 1) goods.setCommentVolume(goods.getCommentVolume() + 1);
        if (! goodsService.updateById(goods)) return new BaseResDto(Status.ERROR).setMessage("修改商品评论数量失败");
        return new BaseResDto(Status.SUCCESS);
    }

    @Override
    public BaseDataResDto<Integer> GoodsCommentShieldCount() {
        EntityWrapper<GoodsComment> entityWrapper = new EntityWrapper();
        entityWrapper.eq("shield", 0);
        entityWrapper.eq("is_del", 0);
        int count = selectCount(entityWrapper);
        return new BaseDataResDto<Integer>(Status.SUCCESS).setData(count);
    }

}
